#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::string;

void test()
{
    int a = 3;
    int b = 4;
    &a;//ok,左值
    &b;//ok,左值
    /* &(a + b);//error,右值 */

    int *pflag = &a;
    &pflag;//ok,左值
    &*pflag;//ok,左值 

    string s1("hello");//栈对象
    string s2("world");//栈对象
    &s1;//ok,左值
    &s2;//ok，左值
    /* &(s1 + s2);//error,右值 */

    int number = 10;
    int &ref = number;
    &number;//ok,左值
    &ref;//ok,左值
    //非const左值引用是不能绑定到右值的，也就是非const左值引用
    //可以识别左值，但是不能识别右值
    /* int &ref2 = 10;//error */
    /* &10;//error,字面值常量，是右值，不能取地址 */

    //const左值引用既可以绑定到左值，也可以绑定到右值，也就是
    //const左值无法识别绑定的对象是左值还是右值
    const int &ref3 = 10;
    const int &ref4 = number;
    &ref3;//ok, 左值
    &ref4;//ok,左值

    //到目前为止，在C++11之前，我们只能识别左值，不能识别右值
    int value = 10;
    //右值引用可以绑定到右值，可以识别右值
    //右值引用不能绑定到左值，也就是不能识别左值
    int &&rref = 10;//ref是右值引用
    /* int &&rref2 = value;//error */
    //总结：非const左值引用可以识别左值，但是识别不了右值
    //右值引用可以识别右值，但是识别不了左值；
    //const左值引用即可绑定左值，也可以绑定右值，但是无法区分
    //绑定是左值还是右值
    
    &rref;//ok,左值
}

int &&func()
{
    return 10;//右值
}

int main(int argc, char *argv[])
{
    test();
    /* &func();//error,右值引用也可以是右值 */
    return 0;
}

